package com.ecoolex.union.pay.retailer.api.controller;


import com.ecoolex.union.pay.retailer.core.util.UnionPayUplanService;
import com.ecoolex.union.pay.retailer.pojo.UnionPayPopularMerchantDTO;
import com.ecoolex.union.pay.retailer.pojo.UnionPayPopularMerchantProductDTO;
import com.ecoolex.union.pay.retailer.ws.UnionPayOrderPushService;
import com.ecoolex.union.pay.retailer.ws.UnionPayPopularMerchantProductService;
import com.ecoolex.union.pay.retailer.ws.UnionPayPopularMerchantService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.util.comparator.Comparators;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

@RestController
@RequestMapping("uplan")
@CrossOrigin(origins = "*", maxAge = 3600)
public class UPlanController {

    @Autowired
    Gson gson;

    @Autowired
    UnionPayUplanService unionPayUplanService;

    @Reference
    UnionPayPopularMerchantService unionPayPopularMerchantService;

    @Reference
    UnionPayPopularMerchantProductService unionPayPopularMerchantProductService;

    @Reference
    UnionPayOrderPushService unionPayOrderPushService;

    @Autowired
    Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder;

    private ObjectMapper objectMapper;

    @PostConstruct
    public void init(){
       objectMapper = jacksonObjectMapperBuilder.dateFormat(new SimpleDateFormat("yyyyMMddHHmmss"))
                .build();
    }

    /**
     * 获取商户列表
     * @param request
     * @return
     */
    @RequestMapping(value = "merchants", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ResponseEntity<Map<String,String>> merchants(HttpServletRequest request) {
        String serviceId = request.getParameter("serviceId");

        boolean isVerifed = verifySign(request);
        Map<String,String> result = new HashMap<>();
        if(isVerifed){
            result.put("errno","00");
            result.put("errmsg","ok");
            List<UnionPayPopularMerchantDTO>  popularMerchants =  unionPayPopularMerchantService.getPopularMerchantList();
            String json = null;
            try {
                json = objectMapper.writeValueAsString(popularMerchants);

            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            result.put("data",json);
        }else {
            result.put("errno","06");
            result.put("errmsg","verify signature fail");
        }
        String orgin = build(result);
        String resulutSign = Base64.getEncoder().encodeToString(unionPayUplanService.signData(orgin));
        result.put("sign",resulutSign);
        return ResponseEntity.ok(result);
    }

    @RequestMapping(value = "merchant/popularProducts", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ResponseEntity<Map<String,String>> popularProducts(HttpServletRequest request) {
        String serviceId = request.getParameter("serviceId");
        String merchantId = request.getParameter("merchantId");

        boolean isVerifed = verifySign(request);
        Map<String,String> result = new HashMap<>();
        if(isVerifed){
            result.put("errno","00");
            result.put("errmsg","ok");
            List<UnionPayPopularMerchantProductDTO>  popularMerchants =  unionPayPopularMerchantProductService.getPopularProducts(merchantId);
            String json = "";
            try {
                json = objectMapper.writeValueAsString(popularMerchants);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            result.put("data",json);
        }else {
            result.put("errno","06");
            result.put("errmsg","verify signature fail");
        }
        String orgin = build(result);
        String resulutSign = Base64.getEncoder().encodeToString(unionPayUplanService.signData(orgin));
        result.put("sign",resulutSign);
        return ResponseEntity.ok(result);
    }

    @RequestMapping(value = "checkSign", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ResponseEntity checkSign(HttpServletRequest request) {
        boolean isVerifed = verifySign(request);
        return ResponseEntity.ok(isVerifed);
    }

    /**
     * 验证用户签名
     * @param request
     * @return
     */
    private boolean verifySign(HttpServletRequest request){
        String sign = request.getParameter("sign");
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String,String> params = new HashMap<>(parameterMap.size());
        parameterMap.forEach((k,v) ->params.put(k,String.valueOf(v[0])));
        String plainText =  build(params);
        String signature = sign;
        boolean isVerifed = unionPayUplanService.verify(plainText,signature);
        return isVerifed;
    }

    /**
     * 生成签名
     * @param request
     * @return
     */
    @RequestMapping(value = "generateSign", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ResponseEntity generateSign(HttpServletRequest request) {
        Map<String,String> paramters = generateParamterPair(request);
        String plainText =  build(paramters);
        String resulutSign = Base64.getEncoder().encodeToString(unionPayUplanService.signData(plainText));
        paramters.put("sign",resulutSign);
        return ResponseEntity.ok(paramters);
    }

    /**
     * 生成签名对
     * @param request
     * @return
     */
    private Map<String,String> generateParamterPair(HttpServletRequest request){
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String,String> params = new HashMap<>(parameterMap.size());
        parameterMap.forEach((k,v) ->params.put(k,String.valueOf(v[0])));
        return params;
    }




    String build(Map<String,String> params){
        Iterator<String> sorted = params.keySet().stream().filter(name ->!"sign".equals(name)).sorted(Comparators.comparable())
                .iterator();
        StringBuilder stringBuilder = new StringBuilder();
        while (sorted.hasNext()){
            String name = sorted.next();
            stringBuilder.append(name).append("=").append(params.get(name));
            if(sorted.hasNext()){
                stringBuilder.append("&");
            }
        }
        return stringBuilder.toString();
    }

    /*@RequestMapping(value = "push", produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ResponseEntity<Map<String,String>> push(@RequestParam("orderId") Integer orderId) {
        Map<String,String> result = new HashMap<>();
        unionPayOrderPushService.push(orderId);
        return ResponseEntity.ok(result);
    }*/

}
